import axios, { AxiosRequestConfig, AxiosResponse, CancelTokenSource } from 'axios'
import { ElMessage, ElLoading } from 'element-plus'
import type { RequestConfig, ResponseData } from './types'

class HttpRequest {
    private instance: axios.AxiosInstance
    private pendingRequests: Map<string, CancelTokenSource> = new Map()
    private loadingInstance: any = null // 可根据具体UI库调整

    constructor(config: AxiosRequestConfig) {
        this.instance = axios.create(config)
        this.setupInterceptors()
    }

    // 生成请求唯一标识
    private generateReqKey(config: AxiosRequestConfig): string {
        const { method, url, params, data } = config
        return [method, url, JSON.stringify(params), JSON.stringify(data)].join('&')
    }

    // 添加请求到pending队列
    private addPendingRequest(config: AxiosRequestConfig) {
        const key = this.generateReqKey(config)
        const source = axios.CancelToken.source()
        config.cancelToken = config.cancelToken || source.token
        this.pendingRequests.set(key, source)
    }

    // 移除已完成请求
    private removePendingRequest(config: AxiosRequestConfig) {
        const key = this.generateReqKey(config)
        if (this.pendingRequests.has(key)) {
            this.pendingRequests.delete(key)
        }
    }

    // 取消所有pending请求
    public cancelAllPendingRequests() {
        this.pendingRequests.forEach(source => source.cancel('请求已取消'))
        this.pendingRequests.clear()
    }

    // 设置拦截器
    private setupInterceptors() {
        // 请求拦截
        this.instance.interceptors.request.use(
            (config: RequestConfig) => {
                this.removePendingRequest(config)
                this.addPendingRequest(config)

                // 添加token
                const token = localStorage.getItem('token')
                if (token) {
                    config.headers = {
                        ...config.headers,
                        Authorization: `Bearer ${token}`
                    }
                }

                // 显示loading
                if (config.showLoading) {
                    this.loadingInstance = ElLoading.service({ // 以Element Plus为例
                        lock: true,
                        text: '加载中...',
                        background: 'rgba(0, 0, 0, 0.7)'
                    })
                }

                return config
            },
            error => Promise.reject(error)
        )

        // 响应拦截
        this.instance.interceptors.response.use(
            (response: AxiosResponse<ResponseData>) => {
                this.removePendingRequest(response.config)

                // 关闭loading
                if (response.config.showLoading && this.loadingInstance) {
                    this.loadingInstance.close()
                }

                const { data } = response
                console.log(data, 'data');
                if (data.code === 401) {
                    // token过期处理
                    window.location.href = '/login'
                    return Promise.reject(new Error('请重新登录'))
                }

                if (!data.success && !response.config.customError) {
                    // 全局错误提示
                    ElMessage.error(data.message || '请求失败')
                    return Promise.reject(data)
                }

                return data
            },
            error => {
                // 关闭loading
                if (error.config?.showLoading && this.loadingInstance) {
                    this.loadingInstance.close()
                }

                // 错误处理
                if (axios.isCancel(error)) {
                    console.log('请求被取消：', error.message)
                } else {
                    const status = error.response?.status
                    const errorMap: { [key: number]: string } = {
                        400: '请求错误',
                        403: '拒绝访问',
                        404: '请求地址错误',
                        500: '服务器内部错误',
                        502: '网关错误',
                        503: '服务不可用'
                    }
                    const message = errorMap[status] || '连接出错'
                    ElMessage.error(message)
                }
                return Promise.reject(error)
            }
        )
    }

    // 封装核心请求方法
    public request<T = any>(config: RequestConfig): Promise<ResponseData<T>> {
        return this.instance.request(config)
    }

    public get<T = any>(
        url: string,
        params?: any,
        config?: RequestConfig
    ): Promise<ResponseData<T>> {
        return this.request({ ...config, method: 'GET', url, params })
    }

    public post<T = any>(
        url: string,
        data?: any,
        config?: RequestConfig
    ): Promise<ResponseData<T>> {
        return this.request({ ...config, method: 'POST', url, data })
    }

    // 其他方法类似实现...
}

// 实例配置
const http = new HttpRequest({
    baseURL: import.meta.env.VITE_API_BASE_URL,
    timeout: 10000,
    headers: {
        'Content-Type': 'application/json;charset=UTF-8'
    }
})

export default http